package com.example.testdemo.pools;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import org.andengine.entity.sprite.Sprite;

import com.example.testdemo.TankGameActivity;
import com.example.testdemo.kinetic.sprite.TankSprite;
import com.example.testdemo.kinetic.sprite.bullet.Bullet1;
import com.example.testdemo.kinetic.sprite.tank.enemy.EnemyBaseTank;
import com.example.testdemo.kinetic.sprite.tank.enemy.EnemyTank1;
import com.example.testdemo.kinetic.sprite.tank.player.PlayerBaseTank;
import com.example.testdemo.kinetic.sprite.tank.player.PlayerTank1;
import com.example.testdemo.manager.ResourcesManager;
import com.example.testdemo.manager.ScenesManager;
import com.example.testdemo.resources.CharacterResources;
import com.example.testdemo.scenes.stage.BaseStage;

public class BulletPools {
	@SuppressWarnings("unused")
	private final String TAG = BulletPools.class.getSimpleName();

	public final static int ENEMY_BULLET_1 = 0;
	public final static int PLAYER_BULLET_1 = 1;

	private static BulletPools INSTANCE = null;
	private static int mWhichScene = -1;

	public static BulletPools getInstance(int whichScene) {
		if (INSTANCE == null) {
			mWhichScene = whichScene;
			INSTANCE = new BulletPools();
		} else {
			if (mWhichScene != whichScene) {
				INSTANCE.free();
				mWhichScene = whichScene;
				INSTANCE = new BulletPools();
			}
		}

		return INSTANCE;
	}

	private CharacterResources mCharacterResources;
	private BaseStage mOnScene;

	private final int ENEMY_MAX_BULLET = 15;
	private final int PLAYER_MAX_BULLET = 1;
	private LinkedBlockingQueue<Bullet1> mEnemyBullet1Queue = null;
	private LinkedBlockingQueue<Bullet1> mPlayerBullet1Queue = null;

	private BulletPools() {
		mCharacterResources = (CharacterResources) ResourcesManager
		        .getInstance().getResources(
		                ResourcesManager.RESOURCES_CHARACTER);
		mOnScene = (BaseStage) ScenesManager.getInstance().getScene(
		        mWhichScene);
	}

	private void hideBullet(Bullet1 bullet) {
		bullet.clearEnergy();
		bullet.setVisible(false);
		bullet.setIgnoreUpdate(true);
	}

	private void showBullet(Bullet1 bullet) {
		bullet.setIgnoreUpdate(false);
		bullet.setVisible(true);
	}

	public void initBullet(TankGameActivity activity, int owner) {
		if (owner == ENEMY_BULLET_1) {
			mEnemyBullet1Queue = new LinkedBlockingQueue<Bullet1>(
			        ENEMY_MAX_BULLET);
			for (int i = 0; i < ENEMY_MAX_BULLET; i++) {
				Bullet1 bullet = new Bullet1(this, mWhichScene,
				        EnemyTank1.BASE_NAME, Bullet1.BASE_NAME + i, 0, 0,
				        mCharacterResources.mBulletTextureRegion, activity);
				mOnScene.attachChild(bullet);

				mEnemyBullet1Queue.add(bullet);
				hideBullet(bullet);
			}
		} else if (owner == PLAYER_BULLET_1) {
			mPlayerBullet1Queue = new LinkedBlockingQueue<Bullet1>(
			        PLAYER_MAX_BULLET);
			for (int i = 0; i < PLAYER_MAX_BULLET; i++) {
				Bullet1 bullet = new Bullet1(this, mWhichScene,
				        PlayerTank1.BASE_NAME, Bullet1.BASE_NAME + i, 0, 0,
				        mCharacterResources.mBulletTextureRegion, activity);
				mOnScene.attachChild(bullet);

				mPlayerBullet1Queue.add(bullet);
				hideBullet(bullet);
			}
		}
	}

	public Bullet1 getOneBullet(TankSprite tank) {
		if (tank instanceof EnemyBaseTank) {
			for (int i = 0; i < ENEMY_MAX_BULLET; i++) {
				Bullet1 bullet = mEnemyBullet1Queue.poll();
				if (bullet == null) {
					continue;
				}
				mEnemyBullet1Queue.offer(bullet);

				if (!bullet.isVisible()) {
					showBullet(bullet);
					return bullet;
				}
			}
		} else if (tank instanceof PlayerBaseTank) {
			for (int i = 0; i < PLAYER_MAX_BULLET; i++) {
				Bullet1 bullet = mPlayerBullet1Queue.poll();
				if (bullet == null) {
					continue;
				}
				mPlayerBullet1Queue.offer(bullet);

				if (!bullet.isVisible()) {
					showBullet(bullet);
					return bullet;
				}
			}
		}

		return null;
	}

	public List<Sprite> getQueue(int which) {
		switch (which) {
		case ENEMY_BULLET_1:
			return queueToList(mEnemyBullet1Queue);
		case PLAYER_BULLET_1:
			return queueToList(mPlayerBullet1Queue);
		}
		return null;
	}

	private List<Sprite> queueToList(LinkedBlockingQueue<Bullet1> queue) {
		List<Sprite> list = new ArrayList<Sprite>();
		for (Bullet1 b : queue) {
			list.add(b);
		}
		return list;
	}

	public void recycle(Bullet1 bullet) {
		hideBullet(bullet);
	}

	public void free() {
		for (Bullet1 bullet : mEnemyBullet1Queue) {
			bullet.free();
		}
		for (Bullet1 bullet : mPlayerBullet1Queue) {
			bullet.free();
		}
		mEnemyBullet1Queue.clear();
		mPlayerBullet1Queue.clear();
		INSTANCE = null;
	}

}
